package com.abc.tacos.dao.impl;

import com.abc.tacos.bean.Ingredient;
import com.abc.tacos.dao.IngredientRepository;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * @author Kar
 * @version 1.0
 * @date 2022/4/16 21:37
 */
@Repository
public class JdbcIngredientRepository implements IngredientRepository {

    /**
     * 基于属性的依赖注入：
     *
     * @Autowired 不在推荐使用属性/字段注入
     * 1. 不允许声明不可变域
     * 基于字段的依赖注入在声明为final/immutable的字段上不起作用，因为这些字段必须在类实例化时实例化。
     * 声明不可变依赖项的惟一方法是使用基于构造器的依赖注入。
     * <p>
     * 2. 容易违反单一职责设计原则
     * 3. 与依赖注入容器紧密耦合
     * 4. 隐藏了依赖关系
     */
    private JdbcTemplate jdbcTemplate;

    /**
     * 同样可以省去 @Autowired
     *
     * @param jdbcTemplate
     */
    public JdbcIngredientRepository(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    @Override
    public Iterable<Ingredient> findAll() {
        return jdbcTemplate.query("select id, name, type from Ingredient",
                this::mapRowToIngredient);
    }

    @Override
    public Ingredient findById(String id) {
        return jdbcTemplate.queryForObject("select id, name, type from Ingredient where id=?",
                this::mapRowToIngredient, id);
    }

    @Override
    public Ingredient save(Ingredient ingredient) {
        jdbcTemplate.update("insert into Ingredient (id, name, type) values (?, ?, ?)",
                ingredient.getId(),
                ingredient.getName(),
                ingredient.getType().toString());
        return ingredient;
    }

    /**
     * @param rs
     * @param rowNum
     * @return
     * @throws SQLException
     */
    private Ingredient mapRowToIngredient(ResultSet rs, int rowNum) throws SQLException {
        return new Ingredient(
                rs.getString("id"),
                rs.getString("name"),
                Ingredient.Type.valueOf(rs.getString("type")));
    }
}
